#ifndef __tenacitas_interlace_text_core_interlace_tester_h__
#define __tenacitas_interlace_text_core_interlace_tester_h__

#include <iostream>
#include <cstdint>
#include <string>

#include "runtest.h"

#include <tenacitas.interlace_text.core/crosswords.h>

namespace tenacitas {
    namespace interlace_text {
        namespace core {

            class crosswords_tester {
            private:
                struct supplier {
                    typedef core::crosswords<supplier> interlace;
                    typedef std::string text;
                };

                typedef core::layouts<supplier> layouts;
                typedef typename layouts::layout_index layout_index;
                typedef supplier::text text;
                typedef typename text::value_type letter;
                typedef supplier::interlace interlace;
                typedef core::coordinate<supplier> coordinate;
                typedef core::coordinates<supplier> coordinates;
                typedef typename coordinates::index coordinate_index;

                static void print(const layouts & p_layouts) {
                    coordinate _coord = p_layouts.greatest();
                    int16_t _num_lines = static_cast<int16_t>(_coord.get_line())
                        + 1;
                    int16_t _num_cols = static_cast<int16_t>(_coord.get_column())
                        + 1;

                    std::cerr << "num lines = " << _num_lines << ", num cols = "
                              << _num_cols << std::endl;
                    
                    
                    letter _matrix[_num_lines][_num_cols];
                    for (int16_t _l = 0; _l < _num_lines; ++_l) {
                        for (int16_t _c = 0; _c < _num_cols; ++_c) {
                            _matrix[_l][_c] = letter(' ');
                        }
                    }

                    layout_index _size_layouts = p_layouts.get_size();
                    for (layout_index _lay_index = 0;
                         _lay_index < _size_layouts;
                         ++_lay_index) {
                        const coordinates & _coords =
                            p_layouts[_lay_index].get_coordinates();
                        coordinate_index _size_coords = _coords.get_size();
                        for (coordinate_index _coord_index = 0;
                             _coord_index < _size_coords;
                             ++_coord_index) {
                            int16_t _line =
                                static_cast<int16_t>(_coords[_coord_index].get_line());
                            int16_t _col =
                                static_cast<int16_t>(_coords[_coord_index].get_column()); 
                            _matrix[_line][_col] = _coords[_coord_index].get_letter();
                        }
                    }

                    std::cerr << "   ";
                    for (int16_t _c = 0; _c < _num_cols; ++_c) {
                        // std::cerr.width(3);
                        // std::cerr.fill(' ');
                        if (_c < 10) {
                            std::cerr << "  " << _c << " ";
                        }
                        else {
                            std::cerr << " " << _c << " ";
                        }
                        
                    }
                    std::cerr << std::endl;
                    
                    
                    for (int16_t _l = 0; _l < _num_lines; ++_l) {
                        std::cerr.width(2);
                        std::cerr.fill(' ');
                        std::cerr << _l << " | ";
                        for (int16_t _c = 0; _c < _num_cols; ++_c) {
                            std::cerr << _matrix[_l][_c] << " | ";
                        }
                        std::cerr << std::endl;
                    }

                    

                    // std::string _sep((std::string(" | ").size() + 1 ) *
                    //                  _num_cols, '-'); 

                    // for (int16_t _l = 0; _l < _num_lines; ++_l) {
                    //     for (int16_t _c = 0; _l < _num_cols; ++_c) {
                    //         std::cerr << " | " << _matrix[_l][_c];
                    //     }
                    //     std::cerr << " | " << std::endl;
                    // }
                }
                
    

                static bool test1() {
                    std::cerr << "\n+++ crosswords_tester::test1" << std::endl;

                    text _w1("abacaxi");                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test2() {
                    std::cerr << "\n+++ crosswords_tester::test2" << std::endl;

                    text _w1("abacaxi");
                    text _w2("xixi");
                    
                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test3() {
                    std::cerr << "\n+++ crosswords_tester::test3" << std::endl;

                    text _w1("abacaxi");
                    text _w2("xixi");
                    
                    text _w3("bau");
                    
                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }
                
                static bool test4() {
                    std::cerr << "\n+++ crosswords_tester::test4" << std::endl;

                    text _w1("abacaxi");
                    text _w2("xixi");
                    
                    text _w3("bau");
                    
                    text _w4("velha");

                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.add(_w4);
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test5() {
                    std::cerr << "\n+++ crosswords_tester::test5" << std::endl;

                    text _w1("abacaxi");
                    text _w2("xixi");
                    text _w3("bau");
                    text _w4("velha");

                    layouts _layouts;

                    _layouts.add(_w1);
                    _layouts.add(_w2);
                    _layouts.add(_w3);
                    _layouts.add(_w4);
                    _layouts.add("queijo");
                    _layouts.add("quilometro");
                    _layouts.add("viajem");
                    _layouts.add("flamengo");
                    _layouts.add("rouxinol");
                    _layouts.add("limpeza");
                    _layouts.add("paz");
                    _layouts.add("wolverine");
                    _layouts.add("parafuso");
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }
                
                static bool test6() {
                    std::cerr << "\n+++ crosswords_tester::test6" << std::endl;

                    layouts _layouts;

                    _layouts.add("thor");
                    _layouts.add("hulk");
                    _layouts.add("visao");
                    _layouts.add("viuva");
                    _layouts.add("ferro");
                    _layouts.add("america");
                    _layouts.add("arqueiro");
                    _layouts.add("escarlate");
                    _layouts.add("mercurio");
                    _layouts.print(std::cerr);

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    _layouts.print(std::cerr);

                    print(_layouts);

                    return (_rc);
                    
                }

                static bool test7() {
                    std::cerr << "\n+++ crosswords_tester::test7" << std::endl;

                    layouts _layouts;

                    _layouts.add("agravado");

                    _layouts.add("mambo");

                    _layouts.add("cume");
                    
                    _layouts.add("trineto");

                    _layouts.add("wilde");

                    _layouts.add("gole");

                    _layouts.add("rixa");

                    _layouts.add("liso");

                    _layouts.add("imortal");

                    _layouts.add("ag");

                    _layouts.add("martins");

                    _layouts.add("crescido");

                    _layouts.add("socar");

                    _layouts.add("esgalha");

                    _layouts.add("temor");

                    _layouts.add("azul");

                    _layouts.add("tres");

                    _layouts.add("harioldo");

                    _layouts.add("dom");

                    _layouts.add("ferrugem");

                    _layouts.add("pretagil");

                    _layouts.add("af");

                    _layouts.add("sereia");

                    _layouts.add("item");

                    _layouts.add("titanic");

                    _layouts.add("bage");

                    _layouts.add("zero");

                    _layouts.add("oronasal");

                    _layouts.add("atrasados");

                    _layouts.add("gr");

                    _layouts.add("mambo");

                    _layouts.add("rir");

                    _layouts.add("mambo");

                    _layouts.add("animal");

                    _layouts.add("vexar");

                    _layouts.add("atar");

                    _layouts.add("do");

                    _layouts.add("missa");

                    _layouts.add("alo");

                    _layouts.add("md");

                    _layouts.add("beirar");

                    _layouts.add("me");

                    _layouts.add("gosto");

                    _layouts.add("corcel");

                    _layouts.add("ultimo");

                    _layouts.add("meado");

                    _layouts.add("loro");

                    _layouts.add("gozo");

                    _layouts.add("ete");

                    _layouts.add("cumprir");

                    _layouts.add("reto");

                    _layouts.add("feia");

                    _layouts.add("tetano");

                    _layouts.add("terra");

                    _layouts.add("ir");

                    _layouts.add("lisergico");

                    _layouts.add("wingsuit");

                    _layouts.add("gleba");

                    _layouts.add("lhe");

                    _layouts.add("mas");

                    _layouts.add("chama");

                    _layouts.add("ga");

                    _layouts.add("fiel");

                    interlace _org;
                    
                    rc<> _rc = _org(_layouts);

                    if (_rc) {
                        print(_layouts);
                    }

                    return _rc;
                    
                }
                
                    

            public:
                static void run() {
                    runtest(crosswords_tester::test1());
                    runtest(crosswords_tester::test2());
                    runtest(crosswords_tester::test3());
                    runtest(crosswords_tester::test4());
                    runtest(crosswords_tester::test5());
                    runtest(crosswords_tester::test6());
                    runtest(crosswords_tester::test7());
                }

            };

        }
    }
}

#endif
